package plus.run;

import plus.DynamicExtent;

public class Emit {
	public static int org;
	public static void asm(int v) { VM.code[org++] = (byte) v; }
	public static void asm16(int v) { asm(v&255); asm(v>>8); }
	public static void asmBig(int v) { if (v<128) asm(v); else { asm((v&127)|128); asm(v>>7); } }
	
	public static void pop() { asm(VM.POP); }
	public static void bool(boolean value) { asm(value ? VM.TRU : VM.FLS); }
	public static void newArray(int length) { loadInt(length); newArray(); }
	public static void newArray() { asm(VM.NEW); }
	public static void loadInt(int val) {
//		System.err.println("  --  load "+val);
		if (-128 <= val && val <= 127) {
			asm(VM.LDI);
			asm(val);
		} else loadConst(val);
	}
	public static void loadConst(Object val) { asm(VM.LDC); asmBig(VM.newConst(val)); }
	public static void stuffArray() { asm(VM.STF); }
	public static void storeIndex() { asm(VM.STX); }
	public static void loadIndex() { asm(VM.LDX); }
	public static void storeIndex(int index) { loadInt(index); storeIndex(); }
	public static void loadIndex(int index) { loadInt(index); loadIndex(); }
	public static void compareIdentity() { asm(VM.EQO); }
	public static void callThunk() { asm(VM.CTH); }
	
	public static final int offsetToStaticLink = 2;
	public static final int offsetToReturnAddress = 1;
	public static final int offsetToDynamicLink = 0;
	
	public static void staticPtr(int depth) {
		// Crawl up some zero or more public static pointers from the current BP
		// in order to get the right public static link.
		// This relies on setting the BP correctly as the first instruction.
		asm(VM.PUSHBP);
		int hops = DynamicExtent.cur.lexLevel - depth;
		while (hops --> 0) readStack(offsetToStaticLink);
	}
	public static void readStack(int i) { asm(VM.READSTACK); asm(i); }
	public static void enter(int words) {
		assert words<256; // This is a limitation of the current VM.
		asm(VM.ENT);
		asm(words);
	}
	public static void exit(int words) { asm(VM.RET); asm(words); }
	public static void writeStack(int i) { asm(VM.WRITESTACK); asm(i); }
}
